package com.ideaaedi.zoo.diy.artifact.auth.satoken.parser;

import com.ideaaedi.zoo.commonbase.constant.ZooConstant;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;


/**
 * 用户原始的请求路径解析器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 1.0.0
 */
public interface RequestRawPathParser {

    /**
     * 获取用户原始的请求路径
     *
     * <pre>
     *  特别注意：此请求头不应接受外部传值，需要在程序的最外层（如：nginx）移除用户可能
     *           传的请求头 __FROM_INNER_MICROSERVICE_REQUEST__，可避免用户因为这
     *           个越权的问题（虽然可以通过一些加密手段来进行预防，但是还是直接不接受外部传值的方式最佳）
     * </pre>
     *
     * @param request 当前请求
     *
     * @return 用户原始的请求路径
     */
    @NonNull
    default String parseRawRequestPath(@NonNull HttpServletRequest request) {
        String innerRequestFlag = request.getHeader(ZooConstant.FROM_INNER_MICROSERVICE_REQUEST);
        String userRawRequestPath = validateIfRequestFromInner(innerRequestFlag);
        boolean isUserDirectRequest = userRawRequestPath == null;
        String servletPath = request.getServletPath();
        if (isUserDirectRequest) {
            request.setAttribute(ZooConstant.FROM_INNER_MICROSERVICE_REQUEST, servletPath);
            return servletPath;
        } else {
            request.setAttribute(ZooConstant.FROM_INNER_MICROSERVICE_REQUEST, userRawRequestPath);
            return userRawRequestPath;
        }
    }

    /**
     * 校验当前请求是否来自内部
     *
     * @param fromInnerMicroserviceHeader 来自内部请求的请求头标识值
     *                                     <p>
     *                                     请求头键为{@link ZooConstant#FROM_INNER_MICROSERVICE_REQUEST}
     *                                     </p>
     *
     * @return 用户原始的请求path
     *         <p>
     *             注：假设用户请求微服务A（请求的接口路径是path1），微服务A内部调用微服务B（调用微服务B接口路径是path2），
     *                那么这里返回用户的原始请求路径 path1
     *         </p>
     *         <url>
     *             <li>返回值为null时：说明当前请求是用户直接发起的请求（，而不是其它微服务对当前服务的）</li>
     *             <li>返回值不为null时：说明当前请求是来自内部其它微服务的请求，返回值是用户的原始请求路径</li>
     *         </url>
     */
    @Nullable
    default String validateIfRequestFromInner(@Nullable String fromInnerMicroserviceHeader) {
        return fromInnerMicroserviceHeader;
    }
}
